package com.kds.smarthome.service;

import com.kds.smarthome.entity.User;
import com.kds.smarthome.entity.Building;
import com.kds.smarthome.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    public List<User> findAll(Map<String, Object> params) {
        return userMapper.findAll(params);
    }

    public long count(Map<String, Object> params) {
        return userMapper.count(params);
    }

    public User findById(Long id) {
        User user = userMapper.findById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        return user;
    }

    public void createUser(User user) {
        // 检查用户名是否已存在
        if (userMapper.findByUsername(user.getUsername()) != null) {
            throw new RuntimeException("用户名已存在");
        }

        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 设置默认值
        user.setEnabled(true);
        user.setLocked(false);

        userMapper.insertUser(user);

        // 保存用户角色关系
        if (user.getRoles() != null) {
            for (String role : user.getRoles()) {
                userMapper.insertUserRole(user.getId(), role);
            }
        }
    }

    public void updateUser(User user) {
        User existingUser = findById(user.getId());

        // 如果修改了密码，需要加密
        if (user.getPassword() != null && !user.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(existingUser.getPassword());
        }

        userMapper.updateUser(user);

        // 更新角色
        if (user.getRoles() != null) {
            userMapper.deleteUserRoles(user.getId());
            for (String role : user.getRoles()) {
                userMapper.insertUserRole(user.getId(), role);
            }
        }
    }

    public void deleteUser(Long id) {
        // 删除用户角色关系
        userMapper.deleteUserRoles(id);
        // 删除用户
        userMapper.deleteUser(id);
    }

    public void deleteUsers(List<Long> ids) {
        for (Long id : ids) {
            deleteUser(id);
        }
    }

    public User findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

    public boolean validatePassword(String rawPassword, String encodedPassword) {
        if (rawPassword == null || encodedPassword == null) {
            return false;
        }
        try {
            return passwordEncoder.matches(rawPassword, encodedPassword);
        } catch (Exception e) {
            log.error("Password validation error", e);
            return false;
        }
    }

    public Collection<? extends GrantedAuthority> getUserAuthorities(Long userId) {
        List<String> roles = userMapper.findUserRoles(userId);
        return roles.stream()
            .map(role -> new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))
            .collect(Collectors.toList());
    }

    /**
     * 仅用于登录验证的用户查询
     */
    public User findByUsernameForAuth(String username) {
        return userMapper.findByUsernameForAuth(username);
    }

    /**
     * 验证密码是否正确
     * @param userId 用户ID
     * @param rawPassword 原始密码
     * @return 密码是否正确
     */
    public boolean validatePassword(Long userId, String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new RuntimeException("密码不能为空");
        }
        
        User user = findById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        if (user.getPassword() == null) {
            throw new RuntimeException("用户密码数据异常");
        }
        
        return passwordEncoder.matches(rawPassword, user.getPassword());
    }

    /**
     * 修改用户密码
     * @param id 用户ID
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     */
    public void updatePassword(Long id, String oldPassword, String newPassword) {
        // 参数校验
        if (oldPassword == null || oldPassword.trim().isEmpty()) {
            throw new RuntimeException("旧密码不能为空");
        }
        if (newPassword == null || newPassword.trim().isEmpty()) {
            throw new RuntimeException("新密码不能为空");
        }
        
        // 验证旧密码
        if (!validatePassword(id, oldPassword)) {
            throw new RuntimeException("旧密码不正确");
        }
        
        // 加密新密码
        String encodedPassword = passwordEncoder.encode(newPassword);
        
        // 更新密码
        userMapper.updatePassword(id, encodedPassword);
    }

    /**
     * 更新用户锁定状态
     * @param id 用户ID
     * @param locked 是否锁定
     */
    public void updateLockStatus(Long id, Boolean locked) {
        // 检查用户是否存在
        findById(id);
        
        // 更新锁定状态
        userMapper.updateLockStatus(id, locked);
    }

    /**
     * 更新用户启用状态
     * @param id 用户ID
     * @param enabled 是否启用
     */
    public void updateEnabledStatus(Long id, Boolean enabled) {
        // 检查用户是否存在
        findById(id);
        
        // 更新启用状态
        userMapper.updateEnabledStatus(id, enabled);
    }

    /**
     * 获取用户管理的建筑列表
     * @param username 用户名
     * @return 建筑列表
     */
    public List<Building> findUserBuildings(String username) {
        return userMapper.findBuildingsByUsername(username);
    }
    
    /**
     * 获取用户管理的建筑编码列表
     * @param username 用户名
     * @return 建筑编码列表
     */
    public List<String> findUserBuildingCodes(String username) {
        return userMapper.findBuildingCodesByUsername(username);
    }
    
    /**
     * 为用户分配建筑
     * @param username 用户名
     * @param buildingCode 建筑编码
     */
    public void assignBuildingToUser(String username, String buildingCode) {
        // 检查是否已经分配
        if (userMapper.checkUserBuildingExists(username, buildingCode)) {
            throw new RuntimeException("该用户已分配此建筑");
        }
        userMapper.assignBuildingToUser(username, buildingCode);
    }
    
    /**
     * 为用户批量分配建筑
     * @param username 用户名
     * @param buildingCodes 建筑编码列表
     */
    public void assignBuildingsToUser(String username, List<String> buildingCodes) {
        if (buildingCodes != null && !buildingCodes.isEmpty()) {
            for (String buildingCode : buildingCodes) {
                if (!userMapper.checkUserBuildingExists(username, buildingCode)) {
                    userMapper.assignBuildingToUser(username, buildingCode);
                }
            }
        }
    }
    
    /**
     * 移除用户的建筑
     * @param username 用户名
     * @param buildingCode 建筑编码
     */
    public void removeBuildingFromUser(String username, String buildingCode) {
        userMapper.removeBuildingFromUser(username, buildingCode);
    }
    
    /**
     * 移除用户的所有建筑
     * @param username 用户名
     */
    public void removeAllBuildingsFromUser(String username) {
        userMapper.removeAllBuildingsFromUser(username);
    }
    
    /**
     * 设置用户的建筑（替换所有）
     * @param username 用户名
     * @param buildingCodes 建筑编码列表
     */
    public void setUserBuildings(String username, List<String> buildingCodes) {
        // 先移除所有
        userMapper.removeAllBuildingsFromUser(username);
        
        // 添加新的
        if (buildingCodes != null && !buildingCodes.isEmpty()) {
            for (String buildingCode : buildingCodes) {
                userMapper.assignBuildingToUser(username, buildingCode);
            }
        }
    }
    
    /**
     * 检查用户是否有权限管理指定建筑
     * @param username 用户名
     * @param buildingCode 建筑编码
     * @return 是否有权限
     */
    public boolean hasPermissionToBuilding(String username, String buildingCode) {
        return userMapper.checkUserBuildingExists(username, buildingCode);
    }
}
